#include <sstream>
#include <common/Logger.h>
#include "CmdHandler.h"

#include <sstream>

static void write_family_vector(std::ostringstream & oss, const std::vector<CFamily> & info)
{
	oss<<" "<<info.size();
	for(size_t i = 0;i < info.size();++i){
		oss<<" "<<info[i].familyName_
			<<" "<<info[i].groupName_
			<<" "<<info[i].maxNumVersion_
			<<" "<<info[i].maxTtl_
			<<" "<<info[i].deadTime_
			<<std::endl;
	}
}

static void write_group_vector(std::ostringstream & oss, const std::vector<CGroup> & info)
{
	oss<<" "<<info.size();
	for(size_t i = 0;i < info.size();++i){
		oss<<" "<<info[i].groupName_
			<<" "<<info[i].compressMethod_
			<<" "<<info[i].cacheRate_
			<<" "<<info[i].blockSize_
			<<" "<<info[i].maxNumSstable_
			<<" "<<info[i].maxSizeSstable_
			<<" "<<info[i].maxSizeMemtable_
			<<std::endl;
	}
}

static void write_table_info(std::ostringstream & oss, const std::string & table_name, const CTableStruct & s)
{
	oss<<table_name;
	write_family_vector(oss, s.families_);
	write_group_vector(oss, s.groups_);
}

bool CQueryCmdHandler::writeTableInfoFile()
{
	LOCAL_LOGGER(logger,"CQueryCmdHandler::writeTableInfo");
	__WriteStream wds;
	wds.Create(tableInfoFile_.c_str(),O_WRONLY);
	if(!wds.IsOpened()){
		ERROR("cannot open tableInfoFile_="<<tableInfoFile_<<CFile::ErrMsg());
		return false;
	}
	else
	{
		__TableInfoGuard g(tableInfo_.Mutex(), true);

		std::ostringstream oss;

		__TableInfo::iterator iter = tableInfo_.begin();
		while (iter != tableInfo_.end())
		{
			write_table_info(oss, iter->first, iter->second);
			++iter;
		}

		wds<<oss.str();
		wds.Flush();
	}
	return true;
}

static bool read_family_vector(std::istringstream & iss, std::vector<CFamily> & info)
{
	info.clear();
	CFamily f;

	unsigned count;
	iss>>count;

	for (unsigned i=0;i<count;i++)
	{
		iss>>f.familyName_
			>>f.groupName_
			>>f.maxNumVersion_
			>>f.maxTtl_
			>>f.deadTime_;

		if (!iss)
			return false;

		info.push_back(f);
	}
	return true;
}

static bool read_group_vector(std::istringstream & iss, std::vector<CGroup> & info)
{
	info.clear();
	CGroup g;

	unsigned count;
	iss>>count;

	for (unsigned i=0;i<count;i++)
	{
		iss>>g.groupName_
			>>g.compressMethod_
			>>g.cacheRate_
			>>g.blockSize_
			>>g.maxNumSstable_
			>>g.maxSizeSstable_
			>>g.maxSizeMemtable_;

		if(!iss)
			return false;
		info.push_back(g);
	}
	return true;
}

static bool read_table_info(std::istringstream & iss, std::string & table_name, CTableStruct & s)
{
	iss>>table_name;

	if (!iss)
	{
		return false;
	}

	if (!read_family_vector(iss, s.families_))
		return false;

	if (!read_group_vector(iss, s.groups_))
		return false;

	return true;
}

bool CQueryCmdHandler::readTableInfoFile()
{
	LOCAL_LOGGER(logger,"CQueryCmdHandler::readTableInfo");
	__ReadStream rds(tableInfoFile_.c_str());
	if(!rds.IsOpened()){
		WARN("cannot open table info file="<<tableInfoFile_<<CFile::ErrMsg());
		return false;
	}

	__TableInfoGuard g(tableInfo_.Mutex(), false);

	CTableStruct s;
	std::string table_name;

	std::string table_info_str;
	rds>>table_info_str;
	std::istringstream iss(table_info_str);

	while (read_table_info(iss, table_name, s))
	{
		tableInfo_[table_name] = s;
	}

	return true;
}
